<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>组件通信</title>
    <script src="./Vue.js"></script>
</head>

<body>
    <div id="app">
        <div :style="{color}">{{msg2}}</div>
        <div :style="{color:rgbcolor}">字体颜色改变</div>
        data 中定义的是rgbcolor:'10,234,78'
        <pre>-----------------------子组件--------------------</pre>
        <menu-item :msgf="msg1" stat="static" ana-msg="驼峰" @change-color="changeColor"></menu-item>


        <pre>-----------------------插槽1--------------------</pre>
        <slot1></slot1>
        <slot1>我不是默认的了</slot1>
        <pre>-----------------------插槽2--------------------</pre>
        <slot2>
            <template v-slot:header>
                我是插槽的头部
                <p>我也是插槽的头部</p>
                <div v-pre>
                    v-slot一定要用template包起来，否则会报错
                    因为，v-slot一定要用在template上或者组件中
                </div>
            </template>

            <template v-slot:default>
                这个我没有指定名字，所以直接映射到默认的位置。
            </template>

            <template v-slot:footer>
                <div>这个是具名插槽的尾部</div>
            </template>
        </slot2>

        <pre>-----------------------插槽3作用域插槽--------------------</pre>
        <pre>
            作用域插槽，（让父组件，对子组件中的内容进行处理。）
            也就是说，插槽能够访问子组件中才有的数据。
            以下这个例子，有一些注意点：
            1、父亲这里要通过v-slot:name 来获得插槽的属性，一般命名为slotProps，其他也可
            2、slotProps点slot动态绑定的值来访问子组件中的对象
            3、子组件的插槽中要通过:info="student" 来动态绑定要被操作的对象
            4、注意子组件中的父子传值问题。驼峰命名，横杠接受
        </pre>
        <slot3 :studentList="students">
            <template v-slot:some="slotProps">
                <strong v-if="slotProps.info.id===2" style="color: red;">{{slotProps.info.name}}</strong>
                <span v-else>{{slotProps.info.name}}</span>
            </template>
        </slot3>
    </div>




    <pre>----------------------组件传值--------------------</pre>
    <pre>
        父传子的总结：
        1、父传子第一步，在父组件的模板中，以属性的形式，绑定一个值
        2、子组件在props中定义接收的属性，名字要与父亲定义的一致
        3、父组件中如果不是动态绑定，则传递过来的是静态字符串。
        4、父组件如果是动态版定的，则传递给子组件的是动态绑定的值
        5、子组件中，当作data里的值，直接使用即可
        6、如果父组件是以横杠连接的属性，那么子组件在接受的时候要使用驼峰式命名，并且使用的时候也是驼峰式命名
        7、在父亲的模板中，是不能使用驼峰式命名属性的，因为浏览器会忽略大小写。所以要么小写，要么横杠连接
        8、假如是驼峰式，在字符串模板中可以是驼峰式也可以是短横线（总之字符串模板中很随意，啥都可以）
        9、为了省事，大家都使用短横线即可。然后props中接受的时候使用驼峰式接受
        10、props是单向的，即只有从父流向子，子中的值改变不会影响父亲的值（当然这个不建议改，因为改不到父组件，那么父亲改的时候，会把自己改动的覆盖），所以需要子传父
    </pre>

    <pre>
        子传父的总结：
        1、子传父的第一步是在父组件中，给子组件绑定监听事件。
        2、子组件中通过$emit的方式来触发事件，并传递给父组件。第一个参数是自定义事件的名称，第二个参数是传递的数据
    </pre>

    <pre>
        兄弟之间同通信：
        1、兄弟之间通信要通过第三方来通信
        2、兄弟通信要借助eventBus来实现
        3、eventBus实际上就是一个发布订阅的模型。
        4、一个兄弟在创建的时候订阅事件，另一个组件触发事件即可
    </pre>
    <script>
        // 全局注册组件
        Vue.component('menu-item', {
            data() {
                return {

                }
            },
            template: `<div>
                    <div>{{msgf}}</div>
                    <div>{{stat}}</div>
                    <div>{{anaMsg}}</div>
                    <button @click="changeFatherColor">改变父组件的color</button>
                </div>`,
            props: [
                'msgf', 'stat', 'anaMsg'
            ],
            methods: {
                changeFatherColor() {
                    // 其实就是一个发布订阅
                    this.$emit('change-color', 'green')
                }
            }
        })
        // 兄弟通信测试
        // 兄弟之间通信使用eventBus。实际上就是发布订阅,只不过Vue身上有这两个方法，所以可以直接使用
        // 实际上和子传父差不多。
        // 移除的时候用 eventBus.$off('comp2-event');
        const eventBus = new Vue();
        Vue.component('comp1', {
            data() {
                return {
                    num: 0,
                }
            },
            template: `
                <div>
                    <p>comp1的值：{{num}}</p>
                    <button @click="handle">改变comp2的值</button>
                </div>
            `,
            methods: {
                handle() {
                    this.$emit('comp2-event', 2);
                }
            },
            mounted() {
                eventBus.$on('comp1-event', (v) => {
                    this.num += v;
                })
            }
        });
        Vue.component('comp2', {
            data() {
                return {
                    num: 0,
                }
            },
            template: `
                <div>
                    <p>comp2的值：{{num}}</p>
                    <button @click="handle2">改变comp1的值</button>
                </div>
            `,
            methods: {
                handle2() {
                    this.$emit('comp1-event', 3);
                }
            },
            mounted() {
                eventBus.$on('comp2-event', (v) => {
                    this.num += v;
                })
            }
        })


        // 组件插槽--slot
        Vue.component('slot1', {
            template: `
                <!--默认插槽-->
                <div>
                    <slot>我是插槽的默认内容</slot>
                </div>
            `
        });

        Vue.component('slot2', {
            template: `
                <!-- 具名插槽 -->
                <div>
                    <slot name="header"></slot>
                    <slot></slot>
                    <slot name="footer"></slot>
                </div>
            `
        })

        // 作用域插槽--父组件对子组件进行加工处理
        Vue.component('slot3', {
            props: ['studentlist'],
            template: `
            <ul>
                <li v-for="student in studentlist" :key="student.id" >
                    <slot :info="student" name="some">{{student.name}}</slot>
                </li>
            </ul>
            `
        })



        //根实例是父组件，menu-item是子组件
        const vm = new Vue({
            el: '#app',
            data() {
                return {
                    msg1: 'foo',
                    msg2: 'content',
                    color: 'red',
                    rgbcolor: 'rgb(10,200,65)',
                    students: [
                        { id: 1, name: '张三' },
                        { id: 2, name: '李四' },
                        { id: 3, name: '王五' }
                    ]
                }
            },
            methods: {
                changeColor(color) {
                    this.color = color;
                }
            }
        })
    </script>
</body>

</html>